package org.snail.common.dingding.utils;

import lombok.NonNull;
import org.apache.log4j.Logger;
import org.snail.common.StringUtils2;
import org.snail.constant.ErrCodeConstant;
import org.snail.exception.BaseException;
import org.snail.exception.CommonException;

import org.snail.exception.SqlException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;


@Component
public class JedisUtils {

    private static final Logger LOGGER =  Logger.getLogger(JedisUtils.class);
    private static RedisTemplate<Object, Object> redisTemplate;

    /**
     * 在某一缓存中保存hash
     *
     * @param cacheKey  缓存中的键
     *
     */
    public Integer saveHashCache(String cacheKey, Object hashKey, Object hashValue) throws BaseException {
        if (StringUtils.isEmpty(cacheKey) || StringUtils2.objIsNull(hashKey) || StringUtils2.objIsNull(hashValue)){
            LOGGER.error("缓存中参数为空!");
            throw new BaseException(ErrCodeConstant.ILLEGAL_PARAM, "参数不能为空！");
        }
        Integer resultCode;
        try{
            redisTemplate.opsForHash().put(cacheKey, hashKey, hashValue);
            resultCode = 1;
        }catch (Exception e){
            LOGGER.error("saveHashCacheException",e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "saveHashCache 保存至数据库异常！");
        }
        return resultCode;
    }

    /**
     * 在某一缓存中保存hash
     *
     * @param cacheKey  缓存中的键
     *
     */
    public Integer saveHashCache(@NonNull String cacheKey, Map saveMap) throws BaseException {
        int resultCode;
        try{
            redisTemplate.opsForHash().putAll(cacheKey, saveMap);
            resultCode = 1;
        }catch (Exception e){
            LOGGER.error("saveHashCacheException",e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "saveHashCache 保存至数据库异常！", e);
        }
        return resultCode;
    }

    public Integer saveListCache(String cacheKey, List list) throws CommonException {
        int resultCode;
        try {
            redisTemplate.opsForList().rightPushAll(cacheKey,list);
            resultCode=1;
        }catch (Exception e){
            LOGGER.error("saveListCacheException",e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "saveListCacheException 保存至数据库异常！"+e);
        }
        return  resultCode;
    }

    /**
     * 获取list缓存的内容
     * @param key 键
     * @param start 开始
     * @param end 结束  0 到 -1代表所有值
     * @return
    */
    public List getListCache(String key,long start, long end) throws CommonException {
        List attendanceList;
        try {
            attendanceList = redisTemplate.opsForList().range(key, start, end);
        }catch (Exception e){
            LOGGER.error("saveListCacheException",e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "saveListCacheException 保存至数据库异常！", e);
        }
        return  attendanceList;
    }

    public Map getAllHashCache(String cacheName) throws CommonException {
        if (null == cacheName || StringUtils.isEmpty(cacheName)) {
            LOGGER.error("redis查询hash所有值失败！原因：确实redis姓名！");
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "redis查询hash所有值失败！原因：确实redis姓名！");
        }
        Map entries = null;
        try {
             entries = redisTemplate.opsForHash().entries(cacheName);
        } catch (Exception e) {
            LOGGER.error("redis查询hash所有值失败！查询错误", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "redis查询hash所有值失败！查询错误", e);
        }
        return entries;
    }

    public Object getHashCache(String cacheKey, Object hashKey) throws BaseException {
        if (StringUtils.isEmpty(cacheKey) || StringUtils2.objIsNull(hashKey)) {
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "查询Hash redis失败，参数为空");
        }
        Object hashValue;
        try {
            hashValue = redisTemplate.opsForHash().get(cacheKey, hashKey);
        }catch (Exception e){
            LOGGER.error("数据结构为hashMap的redis，获取值失败！", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "数据结构为hashMap的redis，获取值失败！", e);
        }
        return hashValue;
    }

    public Map getCacheMap(String cacheKey) throws CommonException {
        if (StringUtils.isEmpty(cacheKey)){
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "查询Hash redis失败，参数为空!");
        }
        Map hashMap;
        try {
            hashMap = redisTemplate.opsForHash().entries(cacheKey);
        }catch (Exception e){
            LOGGER.error("数据结构为hashMap的redis，获取值失败！", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "数据结构为hashMap的redis，获取值失败！", e);
        }
        return hashMap;
    }

    public Set getKeysForHash (String cacheKey) throws CommonException {
        if (StringUtils.isEmpty(cacheKey)){
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "查询Hash redis失败，参数为空");
        }
        Set<Object> keys = null;
        try {
            keys = redisTemplate.opsForHash().keys(cacheKey);
        }catch (Exception e){
            LOGGER.error("数据结构为hashMap的redis，获取值失败！", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "数据结构为hashMap的redis，获取值失败！", e);
        }
        return keys;
    }


    /**
     * 判断缓存是否存在
     *
     * @param cacheKey   redis键
     * @param hashKey    redis的值
     * @return boolean 是表示存在该键；否相反
     */
    public boolean isKeyExist(Object cacheKey, Object hashKey) throws CommonException {
        boolean existFlag = false;
        if (StringUtils2.objIsNull(cacheKey) || StringUtils2.objIsNull(hashKey)){
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "查询键失败，参数为空");
        }
        try{
            existFlag = redisTemplate.opsForHash().hasKey(cacheKey, hashKey);
        }catch (Exception e){
            LOGGER.error("数据结构为hashMap的redis，查询键是否存在失败！", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "数据结构为hashMap的redis，查询键是否存在失败！", e);
        }
        return existFlag;
    }

    /**
     * 删除某些值
     *
     * @param cacheKey   redis键
     * @param hashKey    redis的值  ====hashMap
     * @return Long 返回删除条数
     */
    public Long deleteKey(String cacheKey, Object hashKey) throws CommonException {
        if (StringUtils.isEmpty(cacheKey) || StringUtils2.objIsNull(hashKey)){
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "参数不能为空！");
        }
        Long deleteNum;
        try {
            deleteNum = redisTemplate.opsForHash().delete(cacheKey, hashKey);
        }catch (Exception e){
            LOGGER.error("数据结构为hashMap的redis，删除键失败！", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "数据结构为hashMap的redis，删除键失败！");
        }
        return deleteNum;
    }

    /**
     * 获取该缓存中的数据
     */
    public Long getCacheSize(String cacheKey) throws CommonException {
        if (StringUtils.isEmpty(cacheKey)){
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "参数不能为空！");
        }
        Long totalNum;
        try {
            totalNum = redisTemplate.opsForHash().size(cacheKey);
        }catch (Exception e){
            LOGGER.error("数据结构为hashMap的redis，删除键失败！", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "数据结构为hashMap的redis，删除键失败！", e);
        }
        return totalNum;
    }

    /**
     * 数据结构
     */
    public void saveValue(String redisName, Object valueObj) throws CommonException {
        if (StringUtils.isEmpty(redisName) || StringUtils2.objIsNull(valueObj)){
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "参数不能为空！");
        }
        try{
            redisTemplate.opsForValue().set(redisName, valueObj);
        }catch (Exception e) {
            LOGGER.error("存储value结构的数据库操作异常！", e);
            throw new CommonException(ErrCodeConstant.DB_ERR, "存储value结构的数据库操作异常！", e);
        }
    }

    /**
     * 查询reidis中数据结构为value的对象
     * @param valueTypeRedisName
     * @return
     */
    public Object getKeysForValue(@NonNull String valueTypeRedisName) throws SqlException {
        Object valueResult;
        try {
            valueResult = redisTemplate.opsForValue().get(valueTypeRedisName);
        } catch (Exception e) {
            LOGGER.error("获取value结构的redis异常", e);
            throw new SqlException(ErrCodeConstant.DB_ERR, "获取value结构的redis异常", e);
        }
        return valueResult;

    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            LOGGER.error("获取redis的key失败"+e);
            return false;
        }
    }

    public void deleteKey(String k) throws CommonException {
        try{
            redisTemplate.delete(k);
        }catch (Exception e){
            LOGGER.error("删除redis key失败");
            throw new CommonException(ErrCodeConstant.DB_ERR, "删除redis key失败！", e);
        }

    }

    /**
     * 添加有序set结合
     * @param redisName 需要存储的数据名称
     * @param objKey  分数值，可以用来比较
     * @param objValue 所需要存入的对象
     */
    public void saveSortedSet(String redisName, Double objKey, Object objValue) throws SqlException {
        try{
            redisTemplate.opsForZSet().add(redisName, objValue, objKey);
        } catch (Exception e) {
            LOGGER.error("存储有序集合失败！失败原因：" + e);
            throw new SqlException(ErrCodeConstant.ILLEGAL_PARAM,"存储有序集合失败!", e);
        }
    }

    public RedisTemplate<Object, Object> getRedisTemplate() {
        return redisTemplate;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate<Object, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}
